/**
 * \file    generator.h
 * \brief   Parser generator.
 * \author  Jérôme LAURENS
 * \version 0.1
 * \date    September 23, 2014
 *
 * Reads a LALR(1) grammar, generates a parser based on a template file.
 * This is based on lemon parser generator, but has strongly been
 * revisited.
 *
 */
#include <iostream>
#include <limits>
#include "rule.h"
#include "symbol.h"
#include "state.h"
#include "item.h"
#include "action.h"
#include "generator.h"
#include "description.h"
#include "item.h"
#include "common.h"

LPP_NAMESPACE_BEGIN

ItemRef const & Generator::get_item(RuleRef const & rule, SymbolIndex const dot) const {
    Rule2Item const & r2i = all_items_m.at(dot);
    ItemRef const & I = r2i.find(rule)->second;
    return I;
}

ItemRef & Generator::get_item(StateRef const & state, RuleRef const & rule, SymbolIndex const dot) {
    if (!state) {
        throw std::logic_error("Unexpected void state in get_item.");
    }
    Rule2Item & r2i = all_items_m[dot];
    if (r2i.count(rule)==0) {
        r2i.emplace(rule,Item::Make(state,rule, dot));
        assert (r2i.count(rule)!=0);
    }
    ItemRef & I = r2i.find(rule)->second;
    return I;
}

/* The FIRST set defines all terminal tokens that can be encountered when beginning to recognize a grammatical symbol.
** Find all non terminals which will generate the empty string.
** Then go back and compute the first sets of every non terminal.
** The first set is the set of all terminal symbols which can begin
** a string generated by that non terminal.
** Only once.
** see http://cstheory.stackexchange.com/questions/2479/quickly-finding-empty-string-producing-nonterminals-in-a-cfg
** end http://www.math.grin.edu/~rebelsky/Courses/CS362/2004S/Outlines/outline.16.html
*/
void Generator::build_nullable() {
    bool change_made;
    do {
        change_made = false;
        for (RuleRef const & rule: grammar_m->rules()) {
            SymbolRef const & lhs = rule->lhs_symbol();
            if (!lhs->is_nullable()) {
                bool rhs_is_nullable = true;
                for (SymbolRef const & rhs: rule->rhs_symbols()) {
                    if (!rhs->is_nullable()) {
                        rhs_is_nullable = false;
                        break;
                    }
                }
                if ((change_made = rhs_is_nullable)) {
                    lhs->is_nullable(true);
                }
            }
        }
    } while (change_made);
    for (RuleRef const & rule: grammar_m->rules()) {
        Index n = 0;
        for (SymbolRef const & symbol: rule->rhs_symbols()) {
            if (!symbol->is_nullable()) {
                ++n;
            }
        }
#warning non_nullable_rhs_count never used ?
        rule->non_nullable_rhs_count(n);
    }
#ifndef NDEBUG
    DEBUG_MESSAGE("BUILD NULLABLE... DONE");
    for (SymbolRef const & S: grammar_m->symbols()) {
        DEBUG_MESSAGE("%s is %snullable",S->short_name().c_str(),(S->is_nullable()?"":"not "));
    }
#endif
    return;
}
void Generator::build_first_sets() {
  // DEBUG_MESSAGE("Entering: build_first_sets");
    // The FIRST set defines all terminal tokens that can be encountered
    // when beginning to recognize a grammatical symbol.
    bool change_made;
    do {
        change_made = false;
        for (RuleRef const & rule: grammar_m->rules()) {
            SymbolRef const & lhs = rule->lhs_symbol();
            for (SymbolRef const & rhs: rule->rhs_symbols()) {
                if  (rhs->is_terminal()) {
                    change_made = lhs->add_to_first_set(rhs) || change_made;
                } else if (rhs->is_multi_terminal()) {
                    change_made = lhs->add_to_first_set(rhs->get_sub_symbols()) || change_made;
                } else if  (lhs==rhs) {
                    if (rhs->is_nullable()) continue;
                } else {
                    // union of lhs->first_set_m and rhs->first_set_m, std::set_union does not help
                    change_made = lhs->add_to_first_set(rhs->get_first_set()) || change_made;
                    if  (rhs->is_nullable()) continue;
                }
                break;
            }
        }
    } while (change_made) ;
    // DEBUG_MESSAGE("Done: build_first_sets");
    return;
}

/* Compute all LR(0) states for the grammar.  Links
** are added between some states so that the LR(1) follow sets
** can be computed later.
*/
void Generator::build_states() {
#ifndef NDEBUG
    DEBUG_MESSAGE("==========  BUILD STATES");
    DEBUG_MESSAGE("SET OF RULES BY INDEX:");
    std::vector<RuleRef> L(grammar_m->rules().begin(),grammar_m->rules().end());
    std::sort(L.begin(),L.end(),[](RuleRef const & L, RuleRef const & R) {
        return L->index()<R->index();
    });
    for (RuleRef const & R: L) {
        DEBUG_MESSAGE("%s",Description()(R).c_str());
    }
#endif
    std::deque<StateRef> Q;
    // the very first state:
    // add a very first set
    StateRefList built_states;
    built_states.emplace_back(std::make_shared<State>(*this,built_states.size()));
    StateRef state = built_states.back();
    RuleRef const & R = grammar_m->accept_rule();
    ItemRef const & I = get_item(state,R,0);
    state->add_core_item(I);
    Q.push_back(state);
#ifndef NDEBUG
    std::stringstream oss;
    for (ItemRef const & item: state->ordered_core_items()) {
        oss<<Description()(item)<<" / ";
    }
    DEBUG_MESSAGE("FIRST STATE'S CORE ITEMS: %s",oss.str().c_str());
#endif
    do {
        // DEBUG_MESSAGE("POP A STATE FROM THE STACK: %lu",Q.size());
        state = Q.front();
        Q.pop_front();
        compute_closure(state);    /* Compute the Item closure */
        // 1) gather the items with the sames symbol after the dot
        std::map<SymbolRef,ItemRefList> map;
        SymbolRefList L; // ordered symbols
        SymbolRefSet S; // no duplicates
        for (ItemRef const & item: state->ordered_items()) {
            if (!item->is_at_end()) {
                SymbolRef const symbol = item->symbol_after_dot();
                if (S.insert(symbol).second) {
                    L.push_back(symbol);
                }
                ItemRefList & list = map[symbol];
                ItemRefSet set;
                if(set.insert(item).second) {
                    list.push_front(item);
                } else {
                    for (ItemRef const & I: set) {
                        if (I==item) {
                            if (I->rule()==item->rule()) {
                                std::cout<<"SAME rule"<<std::endl;
                                std::cout<<Description()(I->rule())<<std::endl;
                                std::cout<<Description()(item->rule())<<std::endl;
                            }
                            throw std::logic_error("ERROR already there");
                        }
                    }
                    if(!set.insert(item).second) {
                        throw std::logic_error("ERROR no possible insertion");
                    }
                }
            }
        }
        std::deque<StateRef> QQ;
        for (SymbolRef const & symbol: L) {
            StateRef next_state_candidate = std::make_shared<State>(*this,built_states.size());
            StateRef & next_state = next_state_candidate;
            for (ItemRef const & other_item: map[symbol]) {
                DEBUG_MESSAGE("NEXT STATE CORE ITEM: %s",Description()(other_item).c_str());
                ItemRef & new_item = get_item(next_state, other_item->rule(),other_item->dot()+1);
                next_state->add_core_item(new_item);
            }
            // find an already existing state with exactly the same core items
            bool new_state = true;
            for (StateRef const & S: built_states) {
                if (next_state == S) {
                    next_state = S;// same reference !!!
                    new_state = false;
                    break;
                }
            }
            if (new_state) {
                built_states.push_back(next_state);
                QQ.push_back(next_state);
#ifndef NDEBUG
                std::stringstream oss;
                for (ItemRef const & item: next_state->ordered_core_items()) {
                    oss<<Description()(item)<<" / ";
                }
                DEBUG_MESSAGE("NEW NEXT STATE: %s",oss.str().c_str());
#endif
            } else {
                DEBUG_MESSAGE("ALREADY NEXT STATE: %s",Description()(state,1).c_str());
            }
            if (symbol->is_multi_terminal()) {
                for (SymbolRef const & S: symbol->get_sub_symbols()) {
                    state->add_shift_action(S,next_state);
                }
            } else {
                state->add_shift_action(symbol,next_state);
            }
        }
        for (StateRef const & state: QQ) {
            Q.push_front(state);
        }
    } while (!Q.empty());
    states_m.swap(built_states);
#ifndef NDEBUG
    DEBUG_MESSAGE("CLOSURES, NUMBER OF STATES:, %lu",states_m.size());
    for (StateRef const & state: states_m) {
        for (ActionRef const & action: state->actions()) {
            DEBUG_MESSAGE("state #%lu -> action: %s",state->index(),Description()(action).c_str());
        }
    }
    DEBUG_MESSAGE("END CLOSURES.");
    DEBUG_MESSAGE("ALL THE CREATED ITEMS:");
    for (auto const & V: all_items_m) {
        for (auto const & VV: V.second) {
            DEBUG_MESSAGE("KNOWN ITEM: %s",Description()(VV.second).c_str());
        }
    }
#endif
    return;
}

void Generator::build_terminal_lookaheads() {
    // for each state, we compute the sets or terminal lookaheads
    // reachable as symbol after dot after zero or more reduction.
    typedef std::set<StateRef> States;
    typedef std::map<Index,SymbolRefSet> Level2Symbols;
    std::map<StateRef,Level2Symbols> M;
    // find the direct terminal lookaheads of states, no reduction
    Index reduction_depth = 0;
    bool no_change = true;
    for (StateRef const & state: states()) {
        Level2Symbols & MM = M[state];
        SymbolRefSet & Ss = MM[reduction_depth];
        for (ItemRef const & item: state->closure_items()) {
            if (!item->is_at_end()) {
                SymbolRef const & symbol = item->symbol_after_dot();
                if (symbol->is_terminal() && Ss.insert(symbol).second) {
                    no_change = state->insert_terminal_lookahead(symbol) && no_change;
                }
            }
        }
    }
    // for the other depths, start to find the shift states
    typedef std::set<StateRef> States;
    std::map<StateRef,States> shifts;
    for (StateRef const & state: states()) {
        States & Ss = shifts[state];
        for (ActionRef const & action: state->actions()) {
            if (action->is_shift()) {
                Ss.insert(action->shift_state());
            }
        }
    }
#ifndef NDEBUG
    DEBUG_MESSAGE("SHIFT-STATES:");
    for (StateRef const & state: states()) {
        std::cout<<state->index()<<"=>";
        String separator="";
        for (StateRef const & shift_state: shifts[state]) {
            std::cout<<separator<<shift_state->index();
            separator="/";
        }
        std::cout<<std::endl;
    }
#endif
    while(no_change) {
        ++reduction_depth;
        for (StateRef const & state: states()) {
            SymbolRefSet & Ss = M[state][reduction_depth];
            bool no_insert = true;
            for (StateRef const & shift_state: shifts[state]) {
                for (SymbolRef const & symbol: M[shift_state][reduction_depth-1]) {
                    if (Ss.insert(symbol).second) {
                        no_insert = state->insert_terminal_lookahead(symbol) && no_insert;
                    }
                }
            }
            no_change = no_insert && no_change;
        }
    }
#ifndef NDEBUG
    DEBUG_MESSAGE("TERMINAL LOOKAHEDS:");
    for (StateRef const & state: states()) {
        std::cout<<state->index()<<"=>";
        String separator="";
        for (SymbolRef const & symbol: state->terminal_lookaheads()) {
            std::cout<<separator<<symbol->short_name();
            separator=",";
        }
        std::cout<<std::endl;
    }
#endif
}

void Generator::sort_states() {
#ifndef NDEBUG
    DEBUG_MESSAGE("SORT STATES...");
    DEBUG_MESSAGE("BEFORE");
    for (StateRef & state: states_m) {
        DEBUG_MESSAGE("%s",Description()(state).c_str());
        for (ActionRef const & action: state->actions()) {
            Format F("(%1%/%2%,%3%)=>%4%");
            F%state->index()%state->id();
            F%action->lookahead()->name();
            F%Description()(action);
            DEBUG_MESSAGE("%s",F.str().c_str());
        }
    }
#endif
    std::sort(states_m.begin()
              , states_m.end()
              , [](StateRef const & A
                 , StateRef const & B) -> bool {
        if (A->id() == 0 && B->id() != 0)
            return true;
        if (A->id() != 0 && B->id() == 0)
            return false;
        if (A->non_terminal_actions_count()>B->non_terminal_actions_count())
            return true;
        if (B->non_terminal_actions_count()>A->non_terminal_actions_count())
            return false;
        if (A->terminal_actions_count()>B->terminal_actions_count())
            return true;
        if (B->terminal_actions_count()>A->terminal_actions_count())
            return false;
        return A->id()<B->id();
    });
    std::cout<<"SORTED STATES:"<<std::endl;
    Index i = 0;
    for (StateRef const & state: states_m) {
        std::cout<<Description()(state,2)<<std::endl;
        std::cout<<i++<<"<->"<<state->id()<<",";
        std::cout<<state->terminal_actions_count()<<","<<state->non_terminal_actions_count()<<std::endl;
    }
    i = 0;
    for (StateRef & state: states_m) {
        state->index(i++);
    }
#ifndef NDEBUG
    DEBUG_MESSAGE("AFTER");
    for (StateRef & state: states_m) {
        DEBUG_MESSAGE("%s",Description()(state).c_str());
        for (ActionRef const & action: state->actions()) {
            Format F("(%1%/%2%,%3%)=>%4%");
            F%state->index()%state->id();
            F%action->lookahead()->name();
            F%Description()(action);
            DEBUG_MESSAGE("%s",F.str().c_str());
        }
    }
    std::cout<<"SHORT SORTED STATES:"<<std::endl;
    for (StateRef const & state: states_m) {
        std::cout<<Description()(state,1)<<std::endl;
    }
    std::cout<<"SORT STATES... DONE"<<std::endl;
#endif
}

/* Compute the reduce actions, and resolve conflicts.
*/
void Generator::build_reduce_actions(bool show_conflicts) {
#ifndef NDEBUG
    DEBUG_MESSAGE("ADDING REDUCE ACTIONS...");
    for (StateRef const & state: states_m) {
        for (ActionRef const & action: state->actions()) {
            DEBUG_MESSAGE("%s",Description()(action).c_str());
        }
    }
#endif
    for (StateRef const & state: states_m) {
        for (ItemRef const & item: state->ordered_items()) {
            if (item->is_at_end()) {
                for (SymbolRef const & lookahead: grammar()->lookahead_symbols()) {
                    ActionRef const & A = state->action(lookahead);
                    if (A) {
                        if (A->is_shift()) {
                            if (show_conflicts) {
                                std::cout << (Format("SR CONFLICT: state %1%, lookahead %2%, shift %3%, reduce %4%\n")
                                              %state->index()
                                              %lookahead->name()
                                              %A->shift_state()->index()
                                              %Description()(item->rule())).str();
                            }
                            SymbolRef const & S = item->rule()->precedence_symbol();
                            if (item->rule()->lhs_symbol()->is_nullable()) {
                                if (lookahead==item->rule()->lhs_symbol()) {
                                    if (show_conflicts) {
                                        std::cout << "Solved by nullability: keep shift." << std::endl;
                                    }
                                } else {
                                    if (show_conflicts) {
                                        std::cout << "Solved by nullability: replace by reduce." << std::endl;
                                    }
                                    //state->add_reduce_action(lookahead,item->rule());
                                }
                            } else if (S==lookahead) {
                                if (lookahead->associativity()==Symbol::Associativity::RIGHT) { /* Use operator */
                                    if (show_conflicts) {
                                        std::cout << "Solved by right associativity: keep shift." << std::endl;
                                    }
                                } else if (lookahead->associativity()==Symbol::Associativity::LEFT) {  /* to break tie */
                                    if (show_conflicts) {
                                        std::cout << "Solved by left associativity: replace shift by reduce." << std::endl;
                                    }
                                    state->add_reduce_action(lookahead,item->rule());
                                } else if (lookahead->associativity()==Symbol::Associativity::NONE) {  /* to break tie */
                                    if (show_conflicts) {
                                        std::cout << "ERROR: inconsistent grammar (no associativity)." << std::endl;
                                    }
                                    ++number_of_errors_m;
                                } else {
                                    if (show_conflicts) {
                                        std::cout << "Solved by default left associativity: replace shift by reduce." << std::endl;
                                    }
                                    state->add_reduce_action(lookahead,item->rule());
                                }
                            } else if (S) {
                                if (!S->has_precedence()) {
                                    throw std::logic_error("Precedence symbols must have precedence (1).");
                                }
                                if (lookahead->has_precedence()) {
                                    if (lookahead->precedence()<S->precedence()) {
                                        if (show_conflicts) {
                                            std::cout << "Solved by precedence: keep shift." << std::endl;
                                        }
                                    } else if (lookahead->precedence()>S->precedence()) {
                                        if (show_conflicts) {
                                            std::cout << "Solved by precedence: replace shift by reduce." << std::endl;
                                        }
                                        state->add_reduce_action(lookahead,item->rule());
                                    } else if (lookahead->associativity()==Symbol::Associativity::RIGHT) { /* Use operator */
                                        if (show_conflicts) {
                                            std::cout << "Solved by right associativity: keep shift." << std::endl;
                                        }
                                    } else if (lookahead->associativity()==Symbol::Associativity::LEFT) {  /* to break tie */
                                        if (show_conflicts) {
                                            std::cout << "Solved by left associativity: replace shift by reduce." << std::endl;
                                        }
                                        state->add_reduce_action(lookahead,item->rule());
                                    } else {
                                        if (show_conflicts) {
                                            std::cout << "ERROR: not enough information to resolve the conflict." << std::endl;
                                        }
                                        ++number_of_errors_m;
                                    }
                                } else {
                                    if (show_conflicts) {
                                        std::cout << "Solved by lack of precedence: replace shift by reduce." << std::endl;
                                    }
                                    state->add_reduce_action(lookahead,item->rule());
                                }
                            } else if (lookahead->has_precedence()) {
                                if (show_conflicts) {
                                    std::cout << "Solved by precedence: keep shift." << std::endl;
                                }
                            } else {
                                if (show_conflicts) {
                                    std::cout << "ERROR: not enough information to resolve the conflict." << std::endl;
                                }
                                ++number_of_errors_m;
                            }
                        } else if (A->is_reduce()) {
                            if(A->reduce_rule()!=item->rule()) {
                                if (show_conflicts) {
                                    std::cout << (Format("RR CONFLICT: state %1%, lookahead %2%, old reduce %3%, new reduce %4%\n")
                                                  %state->index()
                                                  %lookahead->name()
                                                  %Description()(A->reduce_rule())
                                                  %Description()(item->rule())).str();
                                }
                                SymbolRef const & S = A->reduce_rule()->precedence_symbol();
                                SymbolRef const & SS = item->rule()->precedence_symbol();
                                if (S) {
                                    if (!S->has_precedence()) {
                                        throw std::logic_error("Precedence symbols must have precedence (2).");
                                    }
                                    if (SS) {
                                        if (!SS->has_precedence()) {
                                            throw std::logic_error("Precedence symbols must have precedence (3).");
                                        }
                                        if (S->precedence()<SS->precedence()) {
                                            if (show_conflicts) {
                                                std::cout << "Solved by precedence: keep old reduce." << std::endl;
                                            }
                                        } else if (S->precedence()>SS->precedence()) {
                                            if (show_conflicts) {
                                                std::cout << "Solved by precedence: replace by new reduce." << std::endl;
                                            }
                                            state->add_reduce_action(lookahead,item->rule());
                                        } else if (A->reduce_rule()->id()<item->rule()->id()) {
                                            if (show_conflicts) {
                                                std::cout << "Solved by definition order: keep old reduce." << std::endl;
                                            }
                                        } else /* if (A->reduce_rule()->id()>item->rule()->id()) */ {
                                            if (show_conflicts) {
                                                std::cout << "Solved by definition order: replace by new reduce." << std::endl;
                                            }
                                            state->add_reduce_action(lookahead,item->rule());
                                        }
                                    } else {
                                        if (show_conflicts) {
                                            std::cout << "Solved by lack of precedence symbol: keep old reduce." << std::endl;
                                        }
                                    }
                                } else if (SS) {
                                    if (show_conflicts) {
                                        std::cout << "Solved by lack of precedence symbol: replace by new reduce." << std::endl;
                                    }
                                    state->add_reduce_action(lookahead,item->rule());
                                } else if (A->reduce_rule()->id()<item->rule()->id()) {
                                    if (show_conflicts) {
                                        std::cout << "Solved by definition order: keep old reduce." << std::endl;
                                    }
                                } else /* if (A->reduce_rule()->id()>item->rule()->id()) */ {
                                    if (show_conflicts) {
                                        std::cout << "Solved by definition order: replace by new reduce." << std::endl;
                                    }
                                    state->add_reduce_action(lookahead,item->rule());
                                }
                            } else {
                                // not a conflict: same actions
                            }
                        } else {
                            ++number_of_errors_m;
                        }
                    } else {
                        state->add_reduce_action(lookahead,item->rule());
                    }
                }
            }
        }
    }
    DEBUG_MESSAGE("BUILD REDUCE ACTIONS... DONE");
    for (StateRef & state: states_m) {
        state->sort_actions();
    }
#ifndef NDEBUG
    //  consistency test
    for (StateRef & state: states_m) {
        for (ActionRef const & action: state->actions()) {
            Format F("(%1%/%2%,%3%)=>%4%");
            F%state->index()%state->id();
            F%action->lookahead()->name();
            F%Description()(action);
            DEBUG_MESSAGE("%s",F.str().c_str());
        }
        ActionRefMap M;
        for (ActionRef const & action: state->actions()) {
            M.emplace(action->lookahead(),action);
        }
        for (SymbolRef const & symbol: grammar()->lookahead_symbols()) {
            ActionRef A = state->action(symbol);
            ActionRef a;
            if (M.count(symbol)) {
                a = M.at(symbol);
            }
            if (A!=a) {
                Format F("%1% != %2%");
                F%Description()(A);
                F%Description()(a);
                DEBUG_MESSAGE("%s",F.str().c_str());
                throw std::logic_error("Inconsistent state actions.");
            }
        }
    }
#endif
    std::set<RuleRef> Rs(grammar()->rules().begin(),grammar()->rules().end());
    for (StateRef const & state: states_m) {
        for (ActionRef const & action: state->actions()) {
            if (action->is_reduce()) {
                Rs.erase(action->reduce_rule());
            }
        }
    }
    /* Report an error for each rule that can never be reduced. */
    for (RuleRef const & rule: Rs) {
        std::cerr << file_name_m
                  << " error #"<< ++number_of_errors_m
                  << " at line " << rule->rule_line() << ", rule is never reduced: " << Description()(rule)<<std::endl;
    }
    DEBUG_MESSAGE("REPORT ERRORS... DONE");
}

/* Given an action, compute the integer value for that action
** which is to be put in the action table of the generated machine.
** Return negative if no action should be generated.
*/
ActionCode Generator::error_action_code() const {
    return number_of_states() + number_of_rules();
}
ActionCode Generator::other_action_code() const {
    return std::numeric_limits<ActionCode>().max();
}
void Generator::compute_closure(StateRef & state) {
    DEBUG_MESSAGE("COMPUTE CLOSURE OF STATE: %s", Description()(state).c_str());
    ItemRefSet closure_items;
    ItemRefList ordered_items;
    ItemRefList L(state->ordered_items());
    if(!L.empty()) {
        do {
            ItemRef const & item = L.front();
            if (closure_items.insert(item).second) {
                ordered_items.push_back(item);
                DEBUG_MESSAGE("CORE ITEM ADDED: %s",Description()(item).c_str());
                if (!item->is_at_end()) {
                    SymbolRef const dot_S = item->symbol_after_dot();
                    if (dot_S->is_non_terminal()) {
                        for (RuleRef const & new_R: dot_S->get_rules()) {
                            ItemRef & new_item = get_item(state,new_R,0);
                            if (0==closure_items.count(new_item)) {
                                if (true || std::find(L.begin(),L.end(),new_item)==L.end()) {
                                    DEBUG_MESSAGE("CLOSURE ITEM ADDED: %s",Description()(new_item).c_str());
                                    L.push_back(new_item);
                                }
                            }
                        }
//                        if (dot_S->is_nullable()) {
//                            ItemRef & new_item = get_item(state,item->rule(),item->dot()+1);
//                            if (0==closure_items.count(new_item)) {
//                                if (std::find(L.begin(),L.end(),new_item)==L.end()) {
//                                    DEBUG_MESSAGE("NULLABLE CLOSURE ITEM ADDED: %s",Description()(new_item).c_str());
//                                    L.push_back(new_item);
//                                }
//                            }
//                        }
                    }
                }
            }
            L.pop_front();
        } while(!L.empty());
    }
    state->swap_closure_items(closure_items);
    state->swap_ordered_items(ordered_items);
    DEBUG_MESSAGE("ORDERED ITEMS of state %lu:",state->index());
    for (ItemRef const & item: state->ordered_items()) {
        std::cout<<Description()(item)<<std::endl;
    }
  // DEBUG_MESSAGE("Done: compute_closure");
    return;
}

LPP_NAMESPACE_END
